<?php


namespace app\privatearea\controller\v1;


use app\common\cachemodel\privatearea\PrivateAreaUser;
use app\common\lib\exception\ApiException;
use app\common\lib\IAuth;
use app\common\lib\Util;
use app\common\model\AppTelLogin;
use app\common\model\User;
use think\Cache;
use think\Controller;
use think\Db;
use think\Log;
use think\response\Json;

class Login extends Controller
{
    /**
     * 获取手机验证码
     * @return Json
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getCode()
    {
        $tel = input('tel/s', '');

        // 检查手机号是否正确
        if (!$tel || !Util::telRuleCheck($tel, 86))
        {
            return show(config('code.error'), '手机号错误');
        }

        $appType = $this->request->header('app-type');
        if ($appType !== 'WEB' && strpos($appType, 'manage') === false)
        {
            Log::write('私域获取验证码接口，被盗刷，ip=' . $this->request->ip() . ',app-type：' . $appType . ',tel=' . $tel, 'error', true);
            // 假的发送成功
            return show(config('code.success'), '发送成功');
        }

        $telStr = 'privatearea:isSend:' . $tel;
        $isSendCode = Cache::get($telStr, false);
        if ($isSendCode)
        {
            return show(config('code.error'), '操作频繁，请稍后再试～');
        }

        $time = time();// 当前时间  有效时间暂定为十分钟 600s

        $expire = 600;

        $ip = $this->request->ip();

        try
        {
            $data = (new AppTelLogin())->where(['tel' => $tel, 'expire_time' => ['>', $time]])->findOrFail()->toArray();
        }
        catch (\Exception $e)
        {
            $data = [];
        }
        // 十分钟内无已有验证码
        if (empty($data))
        {
            $code = random_int(100000, 999999);// 六位验证码

            $expire_time = $time + $expire;
            try
            {
                Db::table('app_tel_login')->insertGetId([
                    'tel' => "$tel",
                    'create_time' => $time,
                    'expire_time' => $expire_time,
                    'code' => $code,
                ]);
            }
            catch (\Exception $e)
            {
                Log::write('获取手机验证码失败：' . $e->getMessage() . PHP_EOL . '失败行数：' . $e->getLine() . PHP_EOL . '错误文件：【' . $e->getFile() . '】');
                return show(config('code.error'), '发送失败');
            }

        } else
        {
            $code = $data['code'];
        }
        // 登录或绑定
        $result = Util::sendHySms([$tel], '', 49273, ['valid_code' => $code]);
        if (!$result['success'])
        {
            return show(config('code.error'), '发送失败');
        } else
        {
            // 缓存 验证码 10分钟
            Cache::set('privatearea:tel_code:' . $tel, $code, 600);
        }
        Cache::set($telStr, true, 50);
        // 记录短信日志
        model('log')->save([
            'tel' => $tel,
            'ip' => $ip,
            'create_time' => $time,
            'type' => 1,
        ]);
        return show(config('code.success'), '发送成功');
    }


    public function login()
    {
        $tel = input('tel/s', '');
        $code = input('code/s', '');
        $channelId = $this->request->header('channel',0);

        $time = $this->request->time();
        $ip = $this->request->ip();
        $appConfig = config('app');

        // 短信验证码 或 密码是否存在
        if (empty($code))
        {
            return show(config('code.error'), '手机短信验证码');
        }
        // 短信登录时，检测验证码是否正确
        if (!empty($code))
        {
            if (!in_array($tel, $appConfig['mobile'])
                || strpos($appConfig['code'] * (substr($tel, 3, 6)), $code) !== 0)
            {
                //  validate 严格校验
                $mobileCode = Cache::get('privatearea:tel_code:' . $tel);
                if ($code != $mobileCode)
                {
                    return show(config('code.error'), '短信验证码错误');
                }
            }
        }

        $privateAreaUserModel = new PrivateAreaUser();
        $userModel = new User();

        $privateAreaUserInfo = $privateAreaUserModel->where('tel', $tel)->order('id desc')->find();

        $userInfo = null;
        if ($privateAreaUserInfo)
        {
            $userInfo = $userModel->getUserinfo(['id' => $privateAreaUserInfo['uid']]);
            if ($userInfo['tel'] == !$tel)
            {
                $userInfo = null;
            } else
            {
                if ($userInfo['forbidden'] == 1)
                {
                    throw new ApiException('该账号禁止登录');
                }
            }
        }

        if (!$userInfo)
        {   // 判断 用户是否注册准了
            $userInfo = $userModel->where(['tel' => $tel])->field('id,forbidden')->find();
            if ($userInfo && $userInfo['forbidden'] == 1)
            {
                return show(config('code.error'), '该手机号被禁用,登录失败');
            }
        }

        if (!$userInfo)
        {   // 注册
            $user['uen'] = substr(md5($this->request->time(true) . mt_rand(0, 1000000) . uniqid()), 0, 12);
            $user['nickname'] = preg_replace('/(1[3456789]{1}[0-9])[0-9]{4}([0-9]{4})/i', '$1****$2', $tel);
            $user['reg_time'] = $time;
            $user['reg_ip'] = $ip;
            $user['last_login'] = $time;
            $user['last_ip'] = $ip;
            $user['last_active'] = $time;
            $user['status'] = 1;
            $user['sex'] = 0;
            $user['tel'] = $tel;
            $user['is_first_login'] = 1;
            $user['uc_id'] = md5($tel . $this->request->time(true));
            $user['has_self_recode'] = 0;
            $user['channel'] = $channelId;
            try
            {
                $user['id'] = $userModel->insertGetId($user);
            }
            catch (\Exception $e)
            {
                return show(config('code.error'), '注册失败,请稍后重试');
            }
            $userInfo = $user;
        }

        // 生成token  和 token到期时间
        $token = IAuth::setAppLoginToken($tel);
        $data = [
            'token' => $token,
            'token_expire' => strtotime("+" . $appConfig['login_time_out_day'] . " days"),
        ];
        if (!$privateAreaUserInfo)
        {   // 注册
            $d = [
                'uid' => $userInfo['id'],
                'tel' => $tel,
                'token' => $data['token'],
                'token_expire' => $data['token_expire'],
                'channel' => $channelId,
                'create_time' => $time,
                'login_time' => $time,
            ];

            $privateAreaUid = $privateAreaUserModel->insertGetId($d);
        } else
        {
            // 更新 access_token过期时间
            $privateAreaUserModel->SavaData($privateAreaUserInfo['id'], $data);

            $privateAreaUid = $privateAreaUserInfo['id'];
        }

        return show(config('code.success'), '登录成功', [
            'access_token' => $this->encryptWithOpenssl($data['token'] . '||' . $privateAreaUid)
        ]);
    }

    /**
     * 加密字符串
     * @param string $data 字符串
     * @return string
     */
    protected function encryptWithOpenssl($data): string
    {
        try
        {
            $config = config('privatearea');
            return base64_encode(openssl_encrypt($data, $config['aes_method'], $config['aes_key'], OPENSSL_RAW_DATA, $config['aes_iv']));
        }
        catch (\Exception $e)
        {
            return '';
        }

    }
}
